package com.cardone.common.util;

import com.cardone.common.annotation.*;
import com.google.common.collect.*;
import org.apache.commons.lang3.*;
import org.apache.commons.lang3.reflect.*;
import org.springframework.data.annotation.*;
import org.springframework.util.CollectionUtils;
import org.springframework.util.*;
import org.springframework.util.ReflectionUtils.*;

import java.lang.annotation.*;
import java.lang.reflect.*;
import java.util.*;

/**
 * 实体工具
 *
 * @author yaohaitao
 */
public class EntityUtils {
    private EntityUtils() {
    }

    /**
     * 添加：标识属性集合
     *
     * @param properties 属性集合
     * @param o          对象
     * @return 属性集合
     */
    public static String[] addNotNullIdProperties(final String[] properties, final Object o) {
        final String[] notNullIdProperties = EntityUtils.getNotNullIdProperties(o);

        if (ArrayUtils.isEmpty(notNullIdProperties)) {
            return properties;
        }

        return ArrayUtils.addAll(properties, notNullIdProperties);
    }

    /**
     * 添加：标识属性集合
     *
     * @param o 对象
     * @return 属性集合
     */
    public static String[] getNotNullIdProperties(final Object o) {
        final List<Class<? extends Annotation>> annotationClassList = Lists.newArrayList();

        annotationClassList.add(Id.class);

        return EntityUtils.getNotNullProperties(o, annotationClassList);
    }

    /**
     * 获取：不为空值属性集合
     *
     * @param o                   不为空值属性集合
     * @param annotationClassList 标注集合
     * @return 不为空值属性集合
     */
    public static String[] getNotNullProperties(final Object o, final List<Class<? extends Annotation>> annotationClassList) {
        if (CollectionUtils.isEmpty(annotationClassList)) {
            return ArrayUtils.EMPTY_STRING_ARRAY;
        }

        final List<String> notNullPropertieList = Lists.newArrayList();

        ReflectionUtils.doWithFields(o.getClass(), new FieldCallback() {
            @Override
            public void doWith(final Field field) throws IllegalArgumentException, IllegalAccessException {
                final Object value = FieldUtils.readField(field, o, true);

                if (value != null) {
                    notNullPropertieList.add(field.getName());
                }
            }
        }, new FieldFilter() {
            @Override
            public boolean matches(final Field field) {
                for (final Class<? extends Annotation> annotationClass : annotationClassList) {
                    if (field.isAnnotationPresent(annotationClass)) {
                        return true;
                    }
                }

                return false;
            }
        });

        return notNullPropertieList.toArray(ArrayUtils.EMPTY_STRING_ARRAY);
    }

    /**
     * 添加：不为空值属性集合
     *
     * @param properties          属性集合
     * @param o                   对象
     * @param annotationClassList 标注集合
     * @return 不为空值属性集合
     */
    public static String[] addNotNullProperties(final String[] properties, final Object o, final List<Class<? extends Annotation>> annotationClassList) {
        if (CollectionUtils.isEmpty(annotationClassList)) {
            return properties;
        }

        final String[] notNullProperties = EntityUtils.getNotNullProperties(o, annotationClassList);

        if (ArrayUtils.isEmpty(notNullProperties)) {
            return properties;
        }

        return ArrayUtils.addAll(properties, notNullProperties);
    }

    /**
     * 获取：不为空值属性集合
     *
     * @param properties                     属性集合
     * @param o                              不为空值属性集合
     * @param idAnnotationClassList          标识标注集合
     * @param timeSegmentAnnotationClassList 时间间隔标注集合
     * @return 属性集合
     */
    public static String[] addWhereProperties(final String[] properties, final Object o, final List<Class<? extends Annotation>> idAnnotationClassList, final List<Class<? extends Annotation>> timeSegmentAnnotationClassList) {
        String[] whereProperties = EntityUtils.getNotNullProperties(o, idAnnotationClassList);

        if (ArrayUtils.isNotEmpty(whereProperties)) {
            return whereProperties;
        }

        whereProperties = EntityUtils.getNotNullProperties(o, timeSegmentAnnotationClassList);

        if (ArrayUtils.isEmpty(whereProperties)) {
            return properties;
        }

        if (ArrayUtils.isEmpty(properties)) {
            return whereProperties;
        }

        return ArrayUtils.addAll(properties, whereProperties);
    }

    /**
     * 获取：不为空值属性集合
     *
     * @param o                           不为空值属性集合
     * @param properties                  属性集合
     * @param idAnnotationClasss          标识标注集合
     * @param timeSegmentAnnotationClasss 时间间隔标注集合
     * @return 属性集合
     */
    public static String[] getWhereProperties(final Object o, final String... properties) {
        final String[] whereProperties = EntityUtils.getNotNullIdProperties(o);

        if (ArrayUtils.isNotEmpty(whereProperties)) {
            return whereProperties;
        }

        return EntityUtils.addNotNullTimeSegmentProperties(properties, o);
    }

    /**
     * 添加：时间间隔属性集合
     *
     * @param properties 属性集合
     * @param o          对象
     * @return 属性集合
     */
    public static String[] addNotNullTimeSegmentProperties(final String[] properties, final Object o) {
        final String[] notNullTimeSegmentProperties = EntityUtils.getNotNullTimeSegmentProperties(o);

        if (ArrayUtils.isEmpty(notNullTimeSegmentProperties)) {
            return properties;
        }

        return ArrayUtils.addAll(properties, notNullTimeSegmentProperties);
    }

    /**
     * 添加：时间间隔属性集合
     *
     * @param o 对象
     * @return 属性集合
     */
    public static String[] getNotNullTimeSegmentProperties(final Object o) {
        final List<Class<? extends Annotation>> annotationClassList = Lists.newArrayList();

        annotationClassList.add(BeginDate.class);
        annotationClassList.add(EndDate.class);

        return EntityUtils.getNotNullProperties(o, annotationClassList);
    }
}